#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
from typing import List
import numpy as np

from apps.models.data_model import Data

class AbnormalDataFiltering:
    """
    数据筛选工具

    @Author: kindey
    @Date: 2025/6/18
    @Description:
    """
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    @staticmethod
    def iqr_filtering(source_dev_data: List[Data]):
        """
        使用 IQR 方法对数据进行异常值过滤

        :param source_dev_data 原数据列表
        :return 过滤后的数据列表
        """
        AbnormalDataFiltering.logger.info(f"IQR过滤前数据条数：{len(source_dev_data)}条")
        data_values = np.array([dev_data.data_value for dev_data in source_dev_data])
        q1 = np.percentile(data_values, 25)
        q3 = np.percentile(data_values, 75)
        iqr = q3 - q1
        lower_bound = q1 - 1.5 * iqr
        upper_bound = q3 + 1.5 * iqr
        AbnormalDataFiltering.logger.debug(f"q1: {q1};q3: {q3};iqr: {iqr};lower_bound: {lower_bound};upper_bound: {upper_bound}")
        filter_dev_data = [
            dev_data
            for dev_data in source_dev_data
            if lower_bound <= dev_data.data_value <= upper_bound
        ]
        AbnormalDataFiltering.logger.info(f"IQR过滤后数据条数：{len(filter_dev_data)}条")
        return filter_dev_data

    @staticmethod
    def z_score_filtering(source_dev_data: List[Data], z_score_threshold: float):
        """
        使用 Z-score 方法对数据进行异常值过滤

        :param source_dev_data 原数据列表
        :param z_score_threshold Z-score阈值
        :return 过滤后的数据列表
        """
        AbnormalDataFiltering.logger.info(f"Z-Score过滤前数据条数：{len(source_dev_data)}条")
        # 提取 data_value 列表
        data_values = np.array([dev_data.data_value for dev_data in source_dev_data])
        # 计算均值和标准差
        mean = np.mean(data_values)
        std = np.std(data_values)
        AbnormalDataFiltering.logger.debug(f"平均值: {mean};标准差: {std =}")
        # 进行 Z-score 过滤
        if std == 0:
            filter_dev_data = source_dev_data
        else:
            filter_dev_data = [
                dev_data
                for dev_data in source_dev_data
                if abs((dev_data.data_value - mean) / std) <= z_score_threshold
            ]
        AbnormalDataFiltering.logger.info(f"Z-Score过滤后数据条数：{len(filter_dev_data)}条")
        return filter_dev_data